#include "orm.h"

QHash<QString, ObjectFactory> ORMObject::s_typeFactories;

ORMObject::ORMObject(QObject *parent) : QObject(parent), m_id(-1) {
    // 默认使用类名作为表名
    m_tableName = metaObject()->className();
    m_tableName.replace("*", "");
    m_tableName.replace("class ", "");
    // 转为小写并添加复数后缀
    m_tableName = m_tableName.toLower() + "s";
}

ORMObject::~ORMObject() {}

void ORMObject::registerType(const QString& className, ObjectFactory factory) {
    s_typeFactories[className] = factory;
}

ORMObject* ORMObject::createObject(const QString& className) {
    if (s_typeFactories.contains(className)) {
        return s_typeFactories[className]();
    }
    return nullptr;
}

bool ORMObject::save() {
    if (m_tableName.isEmpty())
        return false;

    // 如果表不存在则创建
    if (!QSqlDatabase::database().tables().contains(m_tableName)) {
        if (!createTable())
            return false;
    }

    QStringList properties = getPropertyNames();
    properties.removeOne("objectName"); // 排除QObject的objectName属性

    if (m_id < 0) {
        // INSERT操作
        QString insertQuery = QString("INSERT INTO %1 (").arg(m_tableName);
        QString valuesQuery = "VALUES (";
        QStringList placeholders;

        for (const QString& property : properties) {
            insertQuery += property + ", ";
            placeholders.append(":" + property);
        }

        // 移除最后的逗号和空格
        insertQuery.chop(2);
        valuesQuery += placeholders.join(", ") + ")";
        insertQuery += ") " + valuesQuery;

        QSqlQuery query;
        query.prepare(insertQuery);

        for (const QString& property : properties) {
            query.bindValue(":" + property, property(property.toUtf8()));
        }

        if (query.exec()) {
            m_id = query.lastInsertId().toInt();
            setProperty("id", m_id);
            
            // 保存子对象
            saveChildren();
            
            return true;
        } else {
            qDebug() << "Insert error:" << query.lastError().text();
            return false;
        }
    } else {
        // UPDATE操作
        QString updateQuery = QString("UPDATE %1 SET ").arg(m_tableName);
        QStringList setClauses;

        for (const QString& property : properties) {
            if (property == "id") continue; // 不更新主键
            setClauses.append(QString("%1 = :%1").arg(property));
        }

        updateQuery += setClauses.join(", ") + " WHERE id = :id";

        QSqlQuery query;
        query.prepare(updateQuery);

        for (const QString& property : properties) {
            query.bindValue(":" + property, property(property.toUtf8()));
        }

        if (query.exec()) {
            // 保存子对象
            saveChildren();
            
            return true;
        } else {
            qDebug() << "Update error:" << query.lastError().text();
            return false;
        }
    }
}

bool ORMObject::load(int id) {
    if (m_tableName.isEmpty() || id < 0)
        return false;

    QSqlQuery query;
    query.prepare(QString("SELECT * FROM %1 WHERE id = :id").arg(m_tableName));
    query.bindValue(":id", id);

    if (query.exec() && query.next()) {
        const QMetaObject* metaObject = this->metaObject();
        for (int i = 0; i < metaObject->propertyCount(); ++i) {
            QMetaProperty property = metaObject->property(i);
            QString propertyName = property.name();
            if (query.record().contains(propertyName)) {
                setProperty(propertyName.toUtf8(), query.value(propertyName));
            }
        }

        // 加载子对象
        loadChildren();

        return true;
    }

    return false;
}

bool ORMObject::remove() {
    if (m_tableName.isEmpty() || m_id < 0)
        return false;

    QSqlQuery query;
    query.prepare(QString("DELETE FROM %1 WHERE id = :id").arg(m_tableName));
    query.bindValue(":id", m_id);

    if (query.exec()) {
        m_id = -1;
        return true;
    }

    return false;
}

QVariant ORMObject::foreignKey() const {
    return QVariant(m_id);
}

void ORMObject::saveChildren() {
    // 默认实现为空，由子类重写
}

void ORMObject::loadChildren() {
    // 默认实现为空，由子类重写
}

template<typename T>
bool ORMObject::saveCollectionProperty(const QString& propertyName, const QString& foreignKeyName) {
    QVariant collectionVariant = property(propertyName.toUtf8());
    if (!collectionVariant.isValid())
        return false;

    // 获取属性的元类型名称
    int propertyIndex = metaObject()->indexOfProperty(propertyName.toUtf8());
    if (propertyIndex < 0)
        return false;
        
    QMetaProperty metaProperty = metaObject()->property(propertyIndex);
    QString typeName = metaProperty.typeName();
    
    // 处理QList
    if (typeName.startsWith("QList<")) {
        if (collectionVariant.canConvert<QList<QObject*>>()) {
            QList<QObject*> objectList = collectionVariant.value<QList<QObject*>>();
            for (QObject* obj : objectList) {
                ORMObject* ormObj = qobject_cast<ORMObject*>(obj);
                if (ormObj) {
                    ormObj->setProperty(foreignKeyName.toUtf8(), m_id);
                    ormObj->save();
                }
            }
            return true;
        }
    }
    // 处理QSet
    else if (typeName.startsWith("QSet<")) {
        // 注意：QSet需要提前注册元类型
        if (collectionVariant.userType() == qMetaTypeId<QSet<QObject*>>()) {
            QSet<QObject*> objectSet = collectionVariant.value<QSet<QObject*>>();
            for (QObject* obj : objectSet) {
                ORMObject* ormObj = qobject_cast<ORMObject*>(obj);
                if (ormObj) {
                    ormObj->setProperty(foreignKeyName.toUtf8(), m_id);
                    ormObj->save();
                }
            }
            return true;
        }
    }
    
    return false;
}

template<typename T>
bool ORMObject::loadCollectionProperty(const QString& propertyName, const QString& foreignKeyName) {
    // 获取集合属性的元信息
    int propertyIndex = metaObject()->indexOfProperty(propertyName.toUtf8());
    if (propertyIndex < 0)
        return false;

    QMetaProperty metaProperty = metaObject()->property(propertyIndex);
    QString typeName = metaProperty.typeName(); // 例如: "QList<Address*>"
    
    // 解析集合元素类型
    QString elementType = parseElementType(typeName); // 例如: "Address*"
    
    // 创建查询获取所有关联对象
    QString tableName = elementType;
    tableName.replace("*", "");
    tableName.replace("class ", "");
    tableName = tableName.toLower() + "s";
    
    QSqlQuery query;
    query.prepare(QString("SELECT * FROM %1 WHERE %2 = :fk").arg(tableName, foreignKeyName));
    query.bindValue(":fk", m_id);
    
    if (!query.exec())
        return false;

    // 创建集合对象
    if (typeName.startsWith("QList<")) {
        QList<QObject*> objectList;
        while (query.next()) {
            ORMObject* obj = ORMObject::createObject(elementType);
            if (obj) {
                // 从查询结果填充对象属性
                for (int i = 0; i < obj->metaObject()->propertyCount(); ++i) {
                    QMetaProperty prop = obj->metaObject()->property(i);
                    QString propName = prop.name();
                    if (query.record().contains(propName)) {
                        obj->setProperty(propName.toUtf8(), query.value(propName));
                    }
                }
                objectList.append(obj);
            }
        }
        setProperty(propertyName.toUtf8(), QVariant::fromValue(objectList));
        return true;
    }
    else if (typeName.startsWith("QSet<")) {
        QSet<QObject*> objectSet;
        while (query.next()) {
            ORMObject* obj = ORMObject::createObject(elementType);
            if (obj) {
                // 从查询结果填充对象属性
                for (int i = 0; i < obj->metaObject()->propertyCount(); ++i) {
                    QMetaProperty prop = obj->metaObject()->property(i);
                    QString propName = prop.name();
                    if (query.record().contains(propName)) {
                        obj->setProperty(propName.toUtf8(), query.value(propName));
                    }
                }
                objectSet.insert(obj);
            }
        }
        // 注意：需要注册QSet<QObject*>元类型才能正常工作
        setProperty(propertyName.toUtf8(), QVariant::fromValue(objectSet));
        return true;
    }
    
    return false;
}

bool ORMObject::createTable() {
    QString sql = generateCreateTableSQL();
    QSqlQuery query;
    if (query.exec(sql)) {
        return true;
    } else {
        qDebug() << "Create table error:" << query.lastError().text();
        return false;
    }
}

QString ORMObject::generateCreateTableSQL() {
    QString sql = QString("CREATE TABLE %1 (id INTEGER PRIMARY KEY AUTOINCREMENT").arg(m_tableName);
    QStringList properties = getPropertyNames();
    properties.removeOne("objectName"); // 排除QObject的objectName属性

    const QMetaObject* metaObject = this->metaObject();
    for (const QString& propertyName : properties) {
        if (propertyName == "id") continue; // 已经添加了id字段

        int propertyIndex = metaObject->indexOfProperty(propertyName.toUtf8());
        if (propertyIndex >= 0) {
            QMetaProperty property = metaObject->property(propertyIndex);
            QVariant::Type type = property.type();

            QString sqlType;
            switch (type) {
                case QVariant::Int:
                case QVariant::UInt:
                case QVariant::LongLong:
                case QVariant::ULongLong:
                    sqlType = "INTEGER";
                    break;
                case QVariant::Double:
                    sqlType = "REAL";
                    break;
                case QVariant::String:
                    sqlType = "TEXT";
                    break;
                case QVariant::Date:
                case QVariant::DateTime:
                    sqlType = "DATETIME";
                    break;
                case QVariant::Bool:
                    sqlType = "BOOLEAN";
                    break;
                default:
                    // 对于对象类型，添加外键字段
                    if (property.userType() >= QMetaType::User) {
                        sqlType = "INTEGER";
                        propertyName += "_id"; // 对象类型使用"_id"作为外键字段
                    } else {
                        sqlType = "TEXT"; // 默认作为TEXT存储
                    }
                    break;
            }

            sql += QString(", %1 %2").arg(propertyName, sqlType);
        }
    }

    sql += ")";
    return sql;
}

QStringList ORMObject::getPropertyNames() const {
    QStringList names;
    const QMetaObject* metaObject = this->metaObject();
    for (int i = 0; i < metaObject->propertyCount(); ++i) {
        names.append(metaObject->property(i).name());
    }
    return names;
}

QString parseElementType(const QString& typeName) {
    int start = typeName.indexOf('<') + 1;
    int end = typeName.lastIndexOf('>');
    if (start > 0 && end > start) {
        return typeName.mid(start, end - start);
    }
    return typeName;
}    